//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CBasicModel.cpp>
///	@path	~/src/graphics/xmodel/
///	@date	2007/11/16
///	@desc	Basic model class.

#include "config/config.h"

#include "lib/system/thread_debug.h"

#include "graphics/IEffect.h"
#include "graphics/ITechnique.h"
#include "graphics/IShaderVariable.h"
#include "graphics/xmodel/CBasicModel.h"

namespace xeres {

	IMPL_IOBJECT_CLASS( CBasicModel );

	// ctor
	CBasicModel::CBasicModel( void )
		: m_transform( NULL )
		, m_color( NULL )
		, m_opacity( NULL )
		, m_geometry( NULL )
	{
	}

	// dtor
	CBasicModel::~CBasicModel( void )
	{
	}

	// connect attribute
	bool CBasicModel::ConnectAttribute( const WString& name , RefWeak< IVar > var )
	{
		RUNNING_ON_THREAD( _S("tick|pool*|!_render") );

		if( name == _S("transform") )
		{
			if( var->GetVarTypeID() != MATRIX_TYPE_CLASS_ID )
			{
				TRACE_ERROR( _S("CBasicModel::ConnectAttribute: 'transform' attribute only accepts matrix type.") );
				return false;
			}
			m_transform = var;
		}
		else if( name == _S("color") )
		{
			if( var->GetVarTypeID() != COLOR_TYPE_CLASS_ID )
			{
				TRACE_ERROR( _S("CBasicModel::ConnectAttribute: 'color' attribute only accepts color type.") );
				return false;
			}
			m_color = var;
		}
		else if( name == _S("opacity") )
		{
			if( var->GetVarTypeID() != FLOAT_TYPE_CLASS_ID )
			{
				TRACE_ERROR( _S("CBasicModel::ConnectAttribute: 'opacity' attribute only accepts float type.") );
				return false;
			}
			m_opacity = var;
		}
		else
		{
			TRACE_ERROR( _S("CBasicModel::ConnectAttribute: Additional attribute '%s' is not supported.") ,
				name.c_str() );
			return false;
		}
		return true;
	}

	// disconnect attribute
	bool CBasicModel::DisconnectAttribute( const WString& name )
	{
		RUNNING_ON_THREAD( _S("tick|pool*|!_render") );

		if( name == _S("transform") )
		{
			m_transform = NULL;
		}
		else if( name == _S("color") )
		{
			m_color = NULL;
		}
		else if( name == _S("opacity") )
		{
			m_opacity = NULL;
		}
		else
		{
			TRACE_ERROR( _S("CBasicModel::DisconnectAttribute: Additional attribute '%s' is not supported.") ,
				name.c_str() );
			return false;
		}
		return true;
	}

	void CBasicModel::DisconnectAll( void )
	{
		RUNNING_ON_THREAD( _S("tick|!_render") );

		m_transform = NULL;
		m_color = NULL;
		m_opacity = NULL;
	}

	void CBasicModel::Render( RenderContext& rc )
	{
		// non-batched context
		{
			// set shaders

		}
		// batched context
		{
			// set non-set shaders
		}
		if( m_shader.IsValid() )
		{
			RefWeak<IShader> shader = m_shader->AdaptShader( rc );

			Ref<IShaderVariable> viewproj = shader->GetVariableBySemantic( "WorldViewProj" );
			viewproj->SetMatrix( rc.GetViewProj() );
			m_shader->Draw( rc , m_geometry );
		}
		else
		{
			m_geometry->EstablishBuffer( rc );
			m_geometry->Draw( rc );
		}
	}

	// Batch
	void CBasicModel::Batch( RenderManager& rm )
	{
		rm.BatchModel( this );
	}
	// SetModel
	bool CBasicModel::SetGeometry( RefWeak<IGeometry> geometry , bool replace /*= false */ )
	{
		if( !replace && m_geometry.IsValid() )
		{
			TRACE_WARNING( _S("CBasicModel::SetModel: Geometry exists and will not be replaced.") );
			return false;
		}

		m_geometry = geometry;
		if( m_shader.IsNull() )
		{
			m_shader = m_geometry->GetLayout()->GetDefaultAdapter();
		}
		return true;
	}

} // namespace xeres
